package com.card.server.domain;

import java.util.*;

public enum CardType {

    INVALID,
    CARD_A,             // 单张
    CARD_AA,            // 对子
    CARD_AAA,           // 三不带
    CARD_WZ,            // 王炸（最大炸弹）
    CARD_AAAB,          // 三带一（3+1）
    CARD_AAABB,         // 三带二（3+2）
    CARD_AAAA,          // 四张相同（炸弹）
    CARD_AAAAB,         // 四带一（4+1）
    CARD_AAAABB,        // 四带二（4+2）
    CARD_AABB,          // 连对（至少两对连续对子）
    CARD_ABCDE,         // 顺子（五张及以上连续单张）
    CARD_AAABBBCCC,     // 飞机（至少两个连续三张）
    CARD_AAABBBCCCD,    // 飞机带单张
    CARD_AAABBBCCCDDEE, // 飞机带对子
    CARD_AAA_LAST;      // 最后一手可以是三张

    public static CardType getCardType(List<Card> cards) {
        if (cards == null || cards.isEmpty()) return INVALID;

        Collections.sort(cards); // 按照 size 排序

        int size = cards.size();

        // 单张
        if (size == 1) return CARD_A;

        // 对子
        if (size == 2 && sameNumber(cards, 0, 1)) return CARD_AA;

        // 王炸
        if (size == 2 && isKingPair(cards)) return CARD_WZ;

        // 三张
        if (size == 3 && allSame(cards)) return CARD_AAA;

        // 炸弹
        if (size == 4 && allSame(cards)) return CARD_AAAA;

        // 三带一
        if (size == 4 && isThreeWithOne(cards)) return CARD_AAAB;

        // 三带二
        if (size == 5 && isThreeWithTwo(cards)) return CARD_AAABB;

        // 四带一
        if (size == 5 && isFourWithOne(cards)) return CARD_AAAAB;

        // 四带二
        if (size == 6 && isFourWithTwo(cards)) return CARD_AAAABB;

        // 顺子
        if (isStraight(cards)) return CARD_ABCDE;

        // 连对
        if (isDoubleStraight(cards)) return CARD_AABB;

        // 飞机
        if (isPlane(cards)) return CARD_AAABBBCCC;

        return INVALID;
    }

    // 判断是否为一对王
    private static boolean isKingPair(List<Card> cards) {
        return (cards.get(0).getSize() == 15 && cards.get(1).getSize() == 16) ||
                (cards.get(0).getSize() == 16 && cards.get(1).getSize() == 15);
    }

    // 所有牌点数相同
    private static boolean allSame(List<Card> cards) {
        for (int i = 1; i < cards.size(); i++) {
            if (!sameNumber(cards, 0, i)) return false;
        }
        return true;
    }

    // 是否为三带一
    private static boolean isThreeWithOne(List<Card> cards) {
        Map<String, Integer> countMap = getCountMap(cards);
        if (countMap.size() != 2) return false;

        boolean has3 = false, has1 = false;
        for (int count : countMap.values()) {
            if (count == 3) has3 = true;
            else if (count == 1) has1 = true;
        }
        return has3 && has1;
    }

    // 是否为三带二
    private static boolean isThreeWithTwo(List<Card> cards) {
        Map<String, Integer> countMap = getCountMap(cards);
        if (countMap.size() != 2) return false;

        boolean has3 = false, has2 = false;
        for (int count : countMap.values()) {
            if (count == 3) has3 = true;
            else if (count == 2) has2 = true;
        }
        return has3 && has2;
    }

    // 是否为四带一
    private static boolean isFourWithOne(List<Card> cards) {
        Map<String, Integer> countMap = getCountMap(cards);
        if (countMap.size() != 2) return false;

        boolean has4 = false, has1 = false;
        for (int count : countMap.values()) {
            if (count == 4) has4 = true;
            else if (count == 1) has1 = true;
        }
        return has4 && has1;
    }

    // 是否为四带二
    private static boolean isFourWithTwo(List<Card> cards) {
        Map<String, Integer> countMap = getCountMap(cards);
        if (countMap.size() != 2) return false;

        boolean has4 = false, has2 = false;
        for (int count : countMap.values()) {
            if (count == 4) has4 = true;
            else if (count == 2) has2 = true;
        }
        return has4 && has2;
    }

    // 顺子
    private static boolean isStraight(List<Card> cards) {
        if (cards.size() < 5) return false;

        Set<Integer> sizes = new HashSet<>();
        for (Card c : cards) {
            if (c.getSize() >= 15) return false; // 不允许王参与
            sizes.add(c.getSize());
        }

        if (sizes.size() != cards.size()) return false;

        List<Integer> sorted = new ArrayList<>(sizes);
        Collections.sort(sorted);

        for (int i = 1; i < sorted.size(); i++) {
            if (sorted.get(i) - sorted.get(i - 1) != 1)
                return false;
        }

        return true;
    }

    // 连对
    private static boolean isDoubleStraight(List<Card> cards) {
        if (cards.size() < 4 || cards.size() % 2 != 0) return false;

        Map<String, Integer> countMap = getCountMap(cards);
        for (Integer v : countMap.values()) {
            if (v != 2) return false;
        }

        List<String> keys = new ArrayList<>(countMap.keySet());
        keys.sort(Comparator.comparingInt(Integer::parseInt));

        for (int i = 1; i < keys.size(); i++) {
            if (Integer.parseInt(keys.get(i)) - Integer.parseInt(keys.get(i - 1)) != 1)
                return false;
        }

        return true;
    }

    // 飞机
    private static boolean isPlane(List<Card> cards) {
        if (cards.size() % 3 != 0 || cards.size() < 6) return false;

        Map<String, Integer> countMap = getCountMap(cards);
        for (Integer v : countMap.values()) {
            if (v != 3) return false;
        }

        List<String> keys = new ArrayList<>(countMap.keySet());
        keys.sort(Comparator.comparingInt(Integer::parseInt));

        for (int i = 1; i < keys.size(); i++) {
            if (Integer.parseInt(keys.get(i)) - Integer.parseInt(keys.get(i - 1)) != 1)
                return false;
        }

        return true;
    }

    // 获取每种数字出现次数
    private static Map<String, Integer> getCountMap(List<Card> cards) {
        Map<String, Integer> map = new HashMap<>();
        for (Card card : cards) {
            map.put(card.getNumber(), map.getOrDefault(card.getNumber(), 0) + 1);
        }
        return map;
    }

    // 工具方法：两张牌是否相同
    private static boolean sameNumber(List<Card> cards, int i, int j) {
        return cards.get(i).getNumber().equals(cards.get(j).getNumber());
    }

    // 是否是炸弹类型
    public boolean isBomb() {
        return this == CARD_AAAA || this == CARD_WZ;
    }

    // 是否是简单牌型（单、对、三张）
    public boolean isSingleUse() {
        return this == CARD_A || this == CARD_AA || this == CARD_AAA;
    }

    // 是否是复合牌型（如三带一、连对、顺子等）
    public boolean isComplex() {
        return this == CARD_AAAB || this == CARD_AAABB || this == CARD_AAAAB ||
                this == CARD_AABB || this == CARD_ABCDE || this == CARD_AAABBBCCC;
    }

    // 返回牌型权重，用于比较大小
    public int getWeight() {
        switch (this) {
            case CARD_A: return 1;
            case CARD_AA: return 2;
            case CARD_AAA: return 3;
            case CARD_AAAB: return 4;
            case CARD_AAABB: return 5;
            case CARD_AAAA: return 6;
            case CARD_AAAAB: return 7;
            case CARD_AAAABB: return 8;
            case CARD_AABB: return 9;
            case CARD_ABCDE: return 10;
            case CARD_AAABBBCCC: return 11;
            case CARD_WZ: return 12;
            default: return 0;
        }
    }
}